home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OCFSRC.PAK / AUTODISP.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  7KB  |  226 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectConnections
  3. // Copyright (c) 1994, 1997 by Borland International
  4. //
  5. // $Revision:   2.9  $
  6. //
  7. // OLE Automation - Implementation of TDispatch, a light-weight version
  8. //                  of IDispatch.
  9. // NOTE: See TServedObject for a richer implementation of IDispatch.
  10. //----------------------------------------------------------------------------
  11. #include <ocf/pch.h>
  12. #if !defined(OCF_APPDESC_H)
  13. # include <ocf/appdesc.h>
  14. #endif
  15. #if !defined(OCF_OCREG_H)
  16. # include <ocf/ocreg.h>
  17. #endif
  18. #if !defined(OCF_OCCTRL_H) && defined(BI_PLAT_WIN32)
  19. # include <ocf/occtrl.h>
  20. #endif
  21.  
  22. //
  23. //
  24. //
  25. TUnknown* TDispatchCreator::CreateObject(TObjectDescriptor objDesc,
  26.                                          IUnknown* outer)
  27. {
  28.   return new TDispatch(objDesc, outer);
  29. }
  30.  
  31. //
  32. //
  33. //
  34. IDispatch* TDispatchCreator::CreateDispatch(TObjectDescriptor objDesc,
  35.                                             IUnknown* outer)
  36. {
  37.   TDispatch* obj = new TDispatch(objDesc, outer);
  38.   return *obj;
  39. }
  40.  
  41. DEFINE_QI_OLEBASE(IDispatch,    0x20400L)
  42. DEFINE_COMBASES1 (TDispatchCOM, IDispatch)
  43.  
  44. //
  45. //
  46. //
  47. TDispatch::TDispatch(const TObjectDescriptor& objDesc, IUnknown* outer)
  48.           :Object(const_cast<void*>(objDesc.Object)), Class(objDesc.Class)
  49. {
  50.   SetOuter(outer ? outer
  51.        : &objDesc.Class->Aggregate(const_cast<void*>(objDesc.Object), *this));
  52.   //
  53.   // NOTE: RefCnt = 0 on creation, will ++ in TAutoVal operator(IDispatch*)
  54.   //
  55. }
  56.  
  57. // IDispatch implementation
  58.  
  59. HRESULT _IFUNC
  60. TDispatch::GetTypeInfoCount(unsigned int far* pctinfo)
  61. {
  62.   *pctinfo = 0;
  63.   return HR_NOERROR;
  64. }
  65.  
  66. HRESULT _IFUNC
  67. TDispatch::GetTypeInfo(unsigned int, LCID, ITypeInfo* far*)
  68. {
  69.   return HR_NOTIMPL;
  70. }
  71.  
  72. HRESULT _IFUNC
  73. TDispatch::GetIDsOfNames(const IID far& riid, OLECHAR far* far* names,
  74.                           unsigned int cNames, LCID lcid, DISPID far* dispIds)
  75. {
  76.   if (riid != IID_NULL)
  77.     return HR_DISP_UNKNOWNINTERFACE;
  78.  
  79.   HRESULT retval = HR_NOERROR;
  80.   TAutoSymbol* symbol;
  81.   for (int i = 0; i < cNames; i++) {
  82.     dispIds[i] = -1;
  83.     if (i == 0) {
  84.     symbol = Class->Lookup(OleStr(names[0]), LANGIDFROMLCID(lcid),
  85.                            asAnyCommand, dispIds[0]);
  86.       if (!symbol)
  87.         retval = HR_DISP_UNKNOWNNAME;
  88.     }
  89.     else if (symbol) {
  90.       if (!Class->LookupArg(OleStr(names[i]), LANGIDFROMLCID(lcid), symbol, dispIds[i]))
  91.         retval = HR_DISP_UNKNOWNNAME;
  92.     }
  93.   }
  94.   return retval;
  95. }
  96.  
  97. //
  98. //
  99. //
  100. HRESULT _IFUNC
  101. TDispatch::Invoke(DISPID dispidMember, const IID& /*riid*/, LCID lcid,
  102.                   unsigned short wFlags, DISPPARAMS* dispparams,
  103.                   VARIANT* varResult, EXCEPINFO* exceptInfo,
  104.                   unsigned int* retArgErr)
  105. {
  106.   // Make a copy of the object in case there's this pointer adjustment
  107.   //
  108.   ObjectPtr object = Object;
  109.  
  110.   // Make sure our object is still valid
  111.   //
  112.   if (!object) {
  113.     return HR_DISP_MEMBERNOTFOUND;
  114.   }
  115.  
  116.   // Build an object representing the data passed in
  117.   // NOTE: Here lies the difference between the 'Invoke' of TServedObject
  118.   //       and TDispatch: the last parameter to TAutoStack's constructor.
  119.   //
  120.   TAutoStack stack(dispidMember, dispparams->rgvarg, lcid, dispparams->cArgs,
  121.                    dispparams->cNamedArgs, dispparams->rgdispidNamedArgs, 0);
  122.  
  123.   // Find the symbol we're asked to dispatch to
  124.   //
  125.   stack.Symbol = Class->FindId(dispidMember, object);
  126.  
  127.   if (!stack.Symbol) {
  128. #if defined(BI_PLAT_WIN32)
  129.     // NOTE: This is a 'hack' that allows TServedObject to expose a generic method
  130.     //       that's used for cases when the object does not provide a method
  131.     //       that matches the dispId invoked.
  132.     //       It is used by our container support for sinking non-standard events.
  133.     //
  134.     if ((stack.Symbol = Class->FindId(DISPID_CATCH_ALL, object)) == NULL)
  135. #endif
  136.       return HR_DISP_MEMBERNOTFOUND;
  137.   }
  138.  
  139.   // Check the attribute bits to ensure we support the type
  140.   //
  141.   if (!stack.Symbol->TestFlag(wFlags)) {
  142.     return HR_DISP_MEMBERNOTFOUND;
  143.   }
  144.  
  145.   // Check if we need return result
  146.   // NOTE: Some servers [such as Word.Basic] seem to be very picky about
  147.   //       the distinction between a function and procedure. They are not
  148.   //       as flexible as we are here..
  149.   //
  150.   if (wFlags & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
  151.     varResult = 0;
  152.  
  153.  
  154.   // Check that the number of arguments sent matches what we're expecting
  155.   //
  156. #if defined(BI_PLAT_WIN16)
  157.   if ((stack.ArgSymbolCount = Class->GetArgCount(*stack.Symbol)) +
  158.       ((wFlags & (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF)) != 0) < stack.ArgCount)
  159.     return HR_DISP_BADPARAMCOUNT;
  160.  
  161. #elif defined(BI_PLAT_WIN32)
  162.   // Again here we'll have to relax a little on the param count check since in the
  163.   // case of the DISPID_CATCH_ALL, the handler is a generic one that can handle
  164.   // any number of parameters.
  165.   //
  166.   if (((stack.ArgSymbolCount = Class->GetArgCount(*stack.Symbol)) +
  167.       ((wFlags & (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF)) != 0) < stack.ArgCount) &&
  168.         (stack.Symbol->DispId != DISPID_CATCH_ALL))
  169.     return HR_DISP_BADPARAMCOUNT;
  170.  
  171. #endif
  172.  
  173.   // Dispatch via the command object and hope we're OK
  174.   // NOTE: TDispatchCreator() vs. Creator of TDispatch & TServedObject
  175.   //
  176.   switch(Class->Dispatch(object, TDispatchCreator(), *this, wFlags, stack, (TAutoVal*)varResult)) {
  177.     case TXAuto::xNoError:
  178.           return HR_NOERROR;
  179.  
  180.     case TXAuto::xNotIDispatch:
  181.     case TXAuto::xForeignIDispatch:
  182.           return HR_DISP_BADVARTYPE;
  183.  
  184.     case TXAuto::xValidateFailure:
  185.          *retArgErr = stack.CurrentArg;
  186.           return HR_DISP_OVERFLOW;
  187.  
  188.     case TXAuto::xConversionFailure:
  189.     case TXAuto::xTypeMismatch:
  190.          *retArgErr = stack.CurrentArg;
  191.           return HR_DISP_TYPEMISMATCH;
  192.  
  193.     case TXAuto::xNoArgSymbol:
  194.          *retArgErr = stack.CurrentArg;
  195.           return HR_DISP_PARAMNOTFOUND;
  196.  
  197.     case TXAuto::xParameterMissing:
  198.     case TXAuto::xNoDefaultValue:
  199.           return HR_DISP_PARAMNOTOPTIONAL;
  200.  
  201.     case TXAuto::xErrorStatus:
  202.       if (exceptInfo) {
  203.         exceptInfo->wCode = (unsigned short)stack.ErrorCode;
  204.         exceptInfo->wReserved = 0;
  205.         exceptInfo->bstrSource = 0;   // cmp vs. TServedObject's support
  206.         exceptInfo->bstrDescription =
  207.           NS_CLASSLIB::SysAllocString(stack.ErrorMsg);
  208.         exceptInfo->bstrHelpFile = 0;
  209.         exceptInfo->pfnDeferredFillIn = 0;
  210.  
  211.         // INVESTIGATE: Is there a method to relay better SCODEs ?
  212.         //
  213.         exceptInfo->scode = E_FAIL;
  214.       }
  215.       return HR_DISP_EXCEPTION;
  216.  
  217.   case TXAuto::xExecutionFailure:
  218.   default:
  219.         // INVESTIGATE: Is there a better error code here ?
  220.         //
  221.         return HR_DISP_OVERFLOW;
  222.   }
  223. }
  224.  
  225.  
  226.